/**
 * The WizardPanel user-interface component class
 * @class syslib.ui.WizardPanel
 * @author Gabriel Ricci
 */
syslib.ui.WizardPanel = __class(syslib.ui.VisualTag,
/** 
 * @lends syslib.ui.WizardPanel
 */ 
{
	id : null,
	title : "Wizard",
	 
	steps : {},	
	actualStep : null,
	
	target : "_blank",
	action : null,
	
	nextLabel : "Next", 
	previousLabel : "Previous", 
	finishLabel : "Finish", 
	cancelLabel : "Cancel", 

	prepare : function(){
		// load the style
		syslib.loadStyleForComponent("wizard");
		
		// get the tag attributes
		var attributes = this.__attributes;
		
		// start some variables
		this.steps = {};
		this.actualStep = null;
		this.action = null;
		this.target = "_blank";

		// set the class attributes
		this.id = (__valid(attributes.id)) ? attributes.id : syslib.element.generateID();
		if(__valid(attributes.next)){this.nextLabel = attributes.next;}
		if(__valid(attributes.previous)){this.previousLabel = attributes.previous;}
		if(__valid(attributes.finish)){this.finishLabel = attributes.finish;}
		if(__valid(attributes.cancel)){this.cancelLabel = attributes.cancel;}
		if(__valid(attributes.title)){this.title = attributes.title;}
		if(__valid(attributes.action)){this.action = attributes.action;}
		if(__valid(attributes.target)){this.target = attributes.target;}
		
		// return
		return true;
	},

	execute : function(){
		// set the main container tag attributes
		var attributes = __extend(this.__attributes, {
			"id" : this.id, 
			"class" : "accordeon-main-container"
		});

		// create the structure
		var structure = ["div", {"id" : this.id, "class" : "wizard-main-panel"},
			["div", {"class" : "wizard-header", "innerName" : "header"},
				["span", {"class" : "wizard-step-title", "innerName" : "stepTitle"}],
				["span", {"class" : "wizard-title", "innerName" : "title"}, 
					this.title
				]
			],
			["div", {"class" : "wizard-body", "innerName": "body"},
				this.__innerHTML
			], 
			["div", {"class" : "wizard-footer", "innerName" : "footer"},
				["div", {"class" : "wizard-footer-left-buttons", "innerName" : "leftButtons"},
					["span", {"class" : "wizard-button-container", "innerName" : "cancelContainer"},
						["input", {"type" : "button", "class" : "wizard-button", "innerName" : "cancelButton"}]
					]
				],
				["div", {"class" : "wizard-footer-right-buttons", "innerName" : "rightButtons"},
					["span", {"class" : "wizard-button-container", "innerName" : "previousContainer"},
						["input", {"type" : "button", "class" : "wizard-button", "innerName" : "previousButton"}]
					],
					["span", {"class" : "wizard-button-container", "innerName" : "nextContainer"},
						["input", {"type" : "button", "class" : "wizard-button", "innerName" : "nextButton"}]
					],
					["span", {"class" : "wizard-button-container", "innerName" : "finishContainer"},
						["input", {"type" : "button", "class" : "wizard-button", "innerName" : "finishButton"}]
					]
				]
			]
		];

		// create the object
		var wizardPanel = this.createDOM(structure);

		// return
		return wizardPanel;
	},

	finalize : function(){
		var attributes 	= this.__attributes;
		var references	= this.__refs;
		
		// set the labels
		references.cancelButton.value		= this.cancelLabel;
		references.finishButton.value		= this.finishLabel;
		references.previousButton.value	= this.previousLabel;
		references.nextButton.value			= this.nextLabel;
		
		// set the events
		syslib.event.listen('click', references.cancelButton, function(){
			this.onEvent('cancel');
		}.applyTo(this));
		syslib.event.listen('click', references.finishButton, function(){
			this.onEvent('finish');
		}.applyTo(this));
		syslib.event.listen('click', references.nextButton, function(){
			this.onEvent('next');
		}.applyTo(this));
		syslib.event.listen('click', references.previousButton, function(){
			this.onEvent('previous');
		}.applyTo(this));
		
		// update the size and position
		this.updateSizeAndPosition();
		
		// event handlers
		syslib.event.listen("resize", window, function(){
			// update the size and position
			this.updateSizeAndPosition();
			
			// shows body mask
			syslib.ui.util.showBodyMask(1000);
		}.applyTo(this));
		
		// store the wizard in the static storage
		syslib.ui.WizardPanel.registeredWizards[this.id] = this;
	},
	
	onEnterBody : function(){
		// shows body mask
		syslib.ui.util.showBodyMask(1000);
	}, 

	addStep : function(step){
		// check the integrity of the step
		if(!__valid(step) || typeof step !== "object"){ return false; }
		
		// get the steps 
		var steps = this.steps;
		
		// store the step
		steps[step.name] 	= step;

		// hide the step body
		syslib.element.hide(step.__element);
		
		// append the step body to this wizard's body
		this.__refs.body.appendChild(step.__element);

		// return
		return true;
	},

	selectStep : function(name){
		// get the needed variables
		var steps 		= this.steps;
		var references 	= this.__refs;
		var found 		= false;

		// search the steps
		for(var stepName in steps){
			// get the current step data
			var step = steps[stepName];
			
			// check if this step isn't the step which needs to be selected 
			if(stepName !== name){
				// hide the step body
				syslib.element.hide(step.__element);
			} else {
				// step found, set as found
				found = true;
				
				// call the select event
				step.onEvent("select");
				
				// set as the actual step
				this.actualStep = name;

				// show or hide the buttons
				(!step.previousEnabled) ? syslib.element.hide(references.previousContainer) : syslib.element.show(references.previousContainer);
				(!step.nextEnabled) ? 	syslib.element.hide(references.nextContainer) : syslib.element.show(references.nextContainer);
				(!step.finishEnabled) ? syslib.element.hide(references.finishContainer) : syslib.element.show(references.finishContainer);
				(!step.cancelEnabled) ? syslib.element.hide(references.cancelContainer) : syslib.element.show(references.cancelContainer);

				// set the title in the wizard
				references.stepTitle.innerHTML = step.__refs.title.innerHTML;
				

				// show the element
				syslib.element.show(step.__element);
			}
		}

		// show error if the step have not been found
		if(!found){ syslib.messages.error("syslib.ui.WizardPanel.selectStep(): Step '" + name + "' not found!"); }
		
		// return
		return found;
	},

	onEvent : function(eventName){
		// get the needed variables
		var references	= this.__refs;
		var actualStep 	= this.steps[this.actualStep];
		
		// call the event handler in the step
		if(actualStep.onEvent(eventName) === false){
			return false;
		}

		// step navigator system
		switch(eventName){
			case "previous" :
				// go to the previous step
				this.selectStep(actualStep.previous);
			break;
			case "next" :
				// check if there's a validator when the next button is clicked
				if(__valid(actualStep.onNext)){
					// create a new anonymous onnext function
					if(actualStep.onNext.indexOf("return ") == -1){
						var onNext = new Function("return " + actualStep.onNext);
					} else {
						var onNext = new Function(actualStep.onNext);
					}
					
					// run the function
					var funcResult = onNext();
					
					// check the result
					if(funcResult == true){
						// go to the next step
						this.selectStep(actualStep.next);
					}
				} else {
					// go to the next step
					this.selectStep(actualStep.next);
				}
			break;
			case "finish" :
				// check if there's an oncancel event setted
				if(__valid(this.__attributes.onfinish)){
					// create a new anonymous onfinish function
					var onFinish = new Function(this.__attributes.onfinish);
					
					// run the created function
					onFinish();
				}
				
				// delete the wizard
				this.__element.parentNode.removeChild(this.__element);
				
				// clear the body mask
				syslib.ui.util.hideBodyMask();
			break;
			case "cancel" :
				// check if there's an oncancel event setted
				if(__valid(this.__attributes.oncancel)){
					eval(this.__attributes.oncancel);
				}
			
				// delete the wizard
				this.__element.parentNode.removeChild(this.__element);
				
				// clear the body mask
				syslib.ui.util.hideBodyMask(1000);
			break;
			default:
				// error
				syslib.messages.error("syslib.ui.WizardPanel.onEvent(): Invalid wizard event name: " + eventName);
			break;
		}
	}, 
	
	updateSizeAndPosition : function(){
		// get the viewport size
		var viewportSize = syslib.ui.size.getViewportSize();
		
		// get the scrollbar size
		var scrollHeight = document.body.scrollTop;
		var scrollWidth = document.body.scrollLeft;
		
		// calcule the margin
		var horizontalMargin = (viewportSize.width * 0.02);
		var verticalMargin = (viewportSize.height * 0.02);
		
		// calcule the position and size of the main container
		var height = (viewportSize.height - (verticalMargin * 2)) - 14;
		var width = (viewportSize.width - (horizontalMargin * 2)) - 14;
		var top = (scrollHeight + verticalMargin);
		var left = (scrollWidth + horizontalMargin);
		
		// calcule the size of the body
		var bodyHeight = (height - 120);
	
		// update the style of the main container
		syslib.element.updateStyle(this.__element, {
			"height" : height + "px", 
			"width" : width + "px", 
			"top" : top + "px",
			"left" : left + "px"
		});
		
		// update the style of the body
		syslib.element.updateStyle(this.__refs.body, {
			"height" : bodyHeight + "px"
		});
	}
});

/**
 * Store the registered wizard panels
 * @static
 */
syslib.ui.WizardPanel.registeredWizards = {};

/**
 * Select an step of the wizardpanel specified by wizardPanelID
 * @static
 */
syslib.ui.WizardPanel.selectStep = function(wizardPanelID, stepName){
	// check if the wizard panel is valid
	if(!__valid(syslib.ui.WizardPanel.registeredWizards[wizardPanelID])){
		// invalid wizard panel, show the error and return
		syslib.messages.error("syslib.ui.WizardPanel.selectStep(): Invalid wizard panel ID: " + wizardPanelID);
		return false;
	}
	
	// get the wizard panel
	var wizardPanel = syslib.ui.WizardPanel.registeredWizards[wizardPanelID];
	
	// select the step
	return wizardPanel.selectStep(stepName);
};